<?php
/**
*
* @package phpBB3
* @version $Id: functions_extra.php,v 1.000 2009/12/30 15:07:35 mikovchain Exp $
* @copyright (c) 2009 phpbbchina.com
* @license http://opensource.org/licenses/gpl-license.php GNU Public License
*
*/

// Extra global functions

/**
*
*/
function user_path_gen($user_id)
{
	if (preg_match('#^\d+#i', $user_id)){
		$length = strlen($user_id);
		if ($length < 6){
			$user_id = sprintf("%06d", $user_id);
			$length = 6;
		}
		$user_path = substr($user_id, 0, $length-5);
		$user_path .= '/' . substr($user_id, $length-5, 3);
		
		return $user_path;
	} else {
		return '000/000';
	}
}

function date_path_gen()
{
	$attach_subdir = date('Ym');
	return $attach_subdir;
}

function mkdeepdir($path)
{
	unset($subpath);
	$path_array = explode('/', $path);
	foreach($path_array AS $path_unit) {
		if($path_unit=='') continue;
		$subpath_array[] = $path_unit;
		$subpath = implode('/', $subpath_array);
		if(!is_dir($subpath)) {
            @mkdir($subpath, 0777);
        }
	}
}

/**
* Simple version of jumpbox, just lists authed categories
*/
function make_category_select($select_id = false, $ignore_id = false, $return_array = false)
{
	global $db, $user, $auth;

	// This query is identical to the jumpbox one
	$sql = 'SELECT * 
		FROM ' . XSPACE_CATEGORIES_TABLE . ' 
		WHERE category_type = ' . CATEGORY_CATEGORY . ' AND creator_id = ' . $user->data['user_id'] . ' 
		ORDER BY left_id ASC';
	$result = $db->sql_query($sql);

	$right = 0;
	$padding_store = array('0' => '');
	$padding = '';
	$category_list = ($return_array) ? array() : '';

	// Sometimes it could happen that categorys will be displayed here not be displayed within the index page
	// This is the result of categorys not displayed at index, having list permissions and a parent of a category with no permissions.
	// If this happens, the padding could be "broken"

	while ($row = $db->sql_fetchrow($result))
	{
		if ($row['left_id'] < $right)
		{
			$padding .= '&nbsp; &nbsp;';
			$padding_store[$row['parent_id']] = $padding;
		}
		else if ($row['left_id'] > $right + 1)
		{
			$padding = (isset($padding_store[$row['parent_id']])) ? $padding_store[$row['parent_id']] : '';
		}

		$right = $row['right_id'];
		$disabled = false;

		if (
			(is_array($ignore_id) && in_array($row['category_id'], $ignore_id)) || $row['category_id'] == $ignore_id
		)
		{
			$disabled = true;
		}

		if ($return_array)
		{
			// Include some more information...
			$selected = (is_array($select_id)) ? ((in_array($row['category_id'], $select_id)) ? true : false) : (($row['category_id'] == $select_id) ? true : false);
			$category_list[$row['category_id']] = array_merge(array('padding' => $padding, 'selected' => ($selected && !$disabled), 'disabled' => $disabled), $row);
		}
		else
		{
			$selected = (is_array($select_id)) ? ((in_array($row['category_id'], $select_id)) ? ' selected="selected"' : '') : (($row['category_id'] == $select_id) ? ' selected="selected"' : '');
			$category_list .= '<option value="' . $row['category_id'] . '"' . (($disabled) ? ' disabled="disabled" class="disabled-option"' : $selected) . '>' . $padding . $row['category_name'] . '</option>';
		}
	}
	$db->sql_freeresult($result);
	unset($padding_store);

	return $category_list;
}

/**
* Get category details
*/
function get_category_info($category_id)
{
	global $db;

	$sql = 'SELECT *
		FROM ' . XSPACE_CATEGORIES_TABLE . "
		WHERE category_id = $category_id";
	$result = $db->sql_query($sql);
	$row = $db->sql_fetchrow($result);
	$db->sql_freeresult($result);

	if (!$row)
	{
		trigger_error("Category #$category_id does not exist", E_USER_ERROR);
	}

	return $row;
}

/**
* Get category branch
*/
function get_category_branch($category_id, $type = 'all', $order = 'descending', $include_category = true)
{
	global $db, $user;

	switch ($type)
	{
		case 'parents':
			$condition = 'c1.left_id BETWEEN c2.left_id AND c2.right_id';
		break;

		case 'children':
			$condition = 'c2.left_id BETWEEN c1.left_id AND c1.right_id';
		break;

		default:
			$condition = 'c2.left_id BETWEEN c1.left_id AND c1.right_id OR c1.left_id BETWEEN c2.left_id AND c2.right_id';
		break;
	}

	$rows = array();

	$sql = 'SELECT c2.*
		FROM ' . XSPACE_CATEGORIES_TABLE . ' c1
		LEFT JOIN ' . XSPACE_CATEGORIES_TABLE . ' c2 ON (' . $condition . ')
		WHERE 
			c1.category_type = ' . CATEGORY_CATEGORY . ' AND 
			c2.category_type = ' . CATEGORY_CATEGORY . ' AND 
			c1.category_id = ' . $category_id . ' AND 
			c1.creator_id = ' . $user->data['user_id'] . ' AND 
			c2.creator_id = ' . $user->data['user_id'] . ' 
		ORDER BY c2.left_id ' . (($order == 'descending') ? 'ASC' : 'DESC');
	$result = $db->sql_query($sql);

	while ($row = $db->sql_fetchrow($result))
	{
		if (!$include_category && $row['category_id'] == $category_id)
		{
			continue;
		}

		$rows[] = $row;
	}
	$db->sql_freeresult($result);

	return $rows;
}

/**
* Remove complete category
*/
function delete_category($category_id, $action_posts='delete', $action_subcategories = 'delete', $posts_to_id, $subcategories_to_id)
{
	global $db, $user, $cache;

	$category_data = get_category_info($category_id);

	$errors = array();
	$log_action_posts = $log_action_categories = $posts_to_name = $subcategories_to_name = '';
	$category_ids = array($category_id);

	if ($action_posts == 'delete')
	{
		$db->sql_query('DELETE FROM ' . XSPACE_TOPIC_MAP_TABLE . ' WHERE category_id = ' . $category_id);
	}
	else if ($action_posts == 'move')
	{
		if (!$posts_to_id)
		{
			$errors[] = $user->lang['NO_DESTINATION_CATEGORY'];
		}
		else
		{
			$sql = 'SELECT category_name
				FROM ' . XSPACE_CATEGORIES_TABLE . '
				WHERE category_type = ' . CATEGORY_CATEGORY . ' AND creator_id = ' . $user->data['user_id'] . ' AND category_id = ' . $posts_to_id;
			$result = $db->sql_query($sql);
			$row = $db->sql_fetchrow($result);
			$db->sql_freeresult($result);

			if (!$row)
			{
				$errors[] = $user->lang['NO_CATEGORY'];
			}
			else
			{
				$sql = 'UPDATE ' . CATEGORY_CATEGORY . ' 
					SET category_id = ' . $posts_to_id . ' 
					WHERE category_id = ' . $category_id;
				$db->sql_query($sql);
			}
		}
	}

	if (sizeof($errors))
	{
		return $errors;
	}

	if ($action_subcategories == 'delete')
	{
		$rows = get_category_branch($category_id, 'children', 'descending', false);

		foreach ($rows as $row)
		{
			$category_ids[] = $row['category_id'];
			$db->sql_query('DELETE FROM ' . XSPACE_TOPIC_MAP_TABLE . ' WHERE category_id = ' . $row['category_id']);
		}

		$diff = sizeof($category_ids) * 2;

		$sql = 'DELETE FROM ' . XSPACE_CATEGORIES_TABLE . '
			WHERE ' . $db->sql_in_set('category_id', $category_ids);
		$db->sql_query($sql);
	}
	else if ($action_subcategories == 'move')
	{
		if (!$subcategories_to_id)
		{
			$errors[] = $user->lang['NO_DESTINATION_FORUM'];
		}
		else
		{
			$sql = 'SELECT category_name
				FROM ' . XSPACE_CATEGORIES_TABLE . '
				WHERE category_id = ' . $subcategories_to_id;
			$result = $db->sql_query($sql);
			$row = $db->sql_fetchrow($result);
			$db->sql_freeresult($result);

			if (!$row)
			{
				$errors[] = $user->lang['NO_CATEGORY'];
			}
			else
			{
				$sql = 'SELECT category_id
					FROM ' . XSPACE_CATEGORIES_TABLE . '
					WHERE category_type = ' . CATEGORY_CATEGORY . ' AND creator_id = ' . $user->data['user_id'] . ' AND parent_id = ' . $category_id;
				$result = $db->sql_query($sql);

				while ($row = $db->sql_fetchrow($result))
				{
					move_category($row['category_id'], $subcategories_to_id);
				}
				$db->sql_freeresult($result);

				// Grab new category data for correct tree updating later
				$category_data = get_category_info($category_id);

				$sql = 'UPDATE ' . XSPACE_CATEGORIES_TABLE . "
					SET parent_id = $subcategories_to_id
					WHERE category_type = " . CATEGORY_CATEGORY . ' AND creator_id = ' . $user->data['user_id'] . ' AND parent_id = ' . $category_id;
				$db->sql_query($sql);

				$diff = 2;
				$sql = 'DELETE FROM ' . XSPACE_CATEGORIES_TABLE . "
					WHERE category_id = $category_id";
				$db->sql_query($sql);
			}
		}

		if (sizeof($errors))
		{
			return $errors;
		}
	}
	else
	{
		$diff = 2;
		$sql = 'DELETE FROM ' . XSPACE_CATEGORIES_TABLE . '
			WHERE category_type = ' . CATEGORY_CATEGORY . ' AND creator_id = ' . $user->data['user_id'] . ' AND category_id = ' . $category_id;
		$db->sql_query($sql);
	}

	// Resync tree
	$sql = 'UPDATE ' . XSPACE_CATEGORIES_TABLE . "
		SET right_id = right_id - $diff
		WHERE category_type = " . CATEGORY_CATEGORY . ' AND creator_id = ' . $user->data['user_id'] . " AND left_id < {$category_data['right_id']} AND right_id > {$category_data['right_id']}";
	$db->sql_query($sql);

	$sql = 'UPDATE ' . XSPACE_CATEGORIES_TABLE . "
		SET left_id = left_id - $diff, right_id = right_id - $diff
		WHERE category_type = " . CATEGORY_CATEGORY . ' AND creator_id = ' . $user->data['user_id'] . " AND left_id > {$category_data['right_id']}";
	$db->sql_query($sql);

	return $errors;
}

/**
* Update category data
*/
function update_category_data(&$category_data)
{
	global $db, $user, $cache, $phpbb_root_path;

	$errors = array();

	if (!$category_data['category_name'])
	{
		$errors[] = $user->lang['CATEGORY_NAME_EMPTY'];
	}

	if (utf8_strlen($category_data['category_desc']) > 4000)
	{
		$errors[] = $user->lang['CATEGORY_DESC_TOO_LONG'];
	}

	// Unset data that are not database fields
	$category_data_sql = $category_data;

	// What are we going to do tonight Brain? The same thing we do everynight,
	// try to take over the world ... or decide whether to continue update
	// and if so, whether it's a new category/cat/link or an existing one
	if (sizeof($errors))
	{
		return $errors;
	}

	if (!isset($category_data_sql['category_id']))
	{
		// no category_id means we're creating a new category
		if ($category_data_sql['parent_id'])
		{
			$sql = 'SELECT left_id, right_id, category_type
				FROM ' . XSPACE_CATEGORIES_TABLE . '
				WHERE category_type = ' . CATEGORY_CATEGORY . ' AND category_id = ' . $category_data_sql['parent_id'];
			$result = $db->sql_query($sql);
			$row = $db->sql_fetchrow($result);
			$db->sql_freeresult($result);

			if (!$row)
			{
				$message = $user->lang['PARENT_NOT_EXIST'] . '<br /><br />' . sprintf($user->lang['RETURN_UCP'], '<a href="' . $this->u_action. '&amp;parent_id=' . $parent_id . '">', '</a>');
				trigger_error($message, E_USER_WARNING);
			}

			$sql = 'UPDATE ' . XSPACE_CATEGORIES_TABLE . '
				SET left_id = left_id + 2, right_id = right_id + 2
				WHERE category_type = ' . CATEGORY_CATEGORY . ' AND creator_id = ' . $user->data['user_id'] . ' AND left_id > ' . $row['right_id'];
			$db->sql_query($sql);

			$sql = 'UPDATE ' . XSPACE_CATEGORIES_TABLE . '
				SET right_id = right_id + 2
				WHERE category_type = ' . CATEGORY_CATEGORY . ' AND creator_id = ' . $user->data['user_id'] . ' AND ' . $row['left_id'] . ' BETWEEN left_id AND right_id';
			$db->sql_query($sql);

			$category_data_sql['left_id'] = $row['right_id'];
			$category_data_sql['right_id'] = $row['right_id'] + 1;
		}
		else
		{
			$sql = 'SELECT MAX(right_id) AS right_id
				FROM ' . XSPACE_CATEGORIES_TABLE . ' 
				WHERE category_type = ' . CATEGORY_CATEGORY . ' AND  creator_id = ' . $user->data['user_id'];
			$result = $db->sql_query($sql);
			$row = $db->sql_fetchrow($result);
			$db->sql_freeresult($result);

			$category_data_sql['left_id'] = $row['right_id'] + 1;
			$category_data_sql['right_id'] = $row['right_id'] + 2;
		}

		$sql = 'INSERT INTO ' . XSPACE_CATEGORIES_TABLE . ' ' . $db->sql_build_array('INSERT', $category_data_sql);
		$db->sql_query($sql);

		$category_data['category_id'] = $db->sql_nextid();
	}
	else
	{
		$row = get_category_info($category_data_sql['category_id']);
		if ($category_data_sql['parent_id'] != $row['parent_id']) {
			move_category($category_data_sql['category_id'], $category_data_sql['parent_id']);
		}

		$sql = 'UPDATE ' . XSPACE_CATEGORIES_TABLE . '
			SET ' . $db->sql_build_array('UPDATE', $category_data_sql) . '
			WHERE category_id = ' . $category_data_sql['category_id'];
		$db->sql_query($sql);
	}
}

/**
* Move category
*/
function move_category($from_id, $to_id)
{
	global $db, $user;

	$to_data = $moved_ids = array();

	$moved_categories = get_category_branch($from_id, 'children', 'descending');
	$from_data = $moved_categories[0];
	$diff = sizeof($moved_categories) * 2;

	$moved_ids = array();
	for ($i = 0; $i < sizeof($moved_categories); ++$i)
	{
		$moved_ids[] = $moved_categories[$i]['category_id'];
	}

	// Resync parents
	$sql = 'UPDATE ' . XSPACE_CATEGORIES_TABLE . "
		SET right_id = right_id - $diff 
		WHERE category_type = " . CATEGORY_CATEGORY . ' AND  creator_id = ' . $user->data['user_id'] . ' 
			AND left_id < ' . $from_data['right_id'] . '
			AND right_id > ' . $from_data['right_id'];
	$db->sql_query($sql);

	// Resync righthand side of tree
	$sql = 'UPDATE ' . XSPACE_CATEGORIES_TABLE . "
		SET left_id = left_id - $diff, right_id = right_id - $diff 
		WHERE category_type = " . CATEGORY_CATEGORY . ' AND  creator_id = ' . $user->data['user_id'] . ' 
			AND left_id > ' . $from_data['right_id'];
	$db->sql_query($sql);

	if ($to_id > 0)
	{
		// Retrieve $to_data again, it may have been changed...
		$to_data = get_category_info($to_id);

		// Resync new parents
		$sql = 'UPDATE ' . XSPACE_CATEGORIES_TABLE . "
			SET right_id = right_id + $diff 
			WHERE category_type = " . CATEGORY_CATEGORY . ' AND  creator_id = ' . $user->data['user_id'] . ' AND ' . 
				$to_data['right_id'] . ' BETWEEN left_id AND right_id 
				AND ' . $db->sql_in_set('category_id', $moved_ids, true);
		$db->sql_query($sql);

		// Resync the righthand side of the tree
		$sql = 'UPDATE ' . XSPACE_CATEGORIES_TABLE . "
			SET left_id = left_id + $diff, right_id = right_id + $diff 
			WHERE category_type = " . CATEGORY_CATEGORY . ' AND  creator_id = ' . $user->data['user_id'] . ' 
				AND  left_id > ' . $to_data['right_id'] . '
				AND ' . $db->sql_in_set('category_id', $moved_ids, true);
		$db->sql_query($sql);

		// Resync moved branch
		$to_data['right_id'] += $diff;

		if ($to_data['right_id'] > $from_data['right_id'])
		{
			$diff = '+ ' . ($to_data['right_id'] - $from_data['right_id'] - 1);
		}
		else
		{
			$diff = '- ' . abs($to_data['right_id'] - $from_data['right_id'] - 1);
		}
	}
	else
	{
		$sql = 'SELECT MAX(right_id) AS right_id
			FROM ' . XSPACE_CATEGORIES_TABLE . '
			WHERE  category_type = ' . CATEGORY_CATEGORY . ' AND creator_id = ' . $user->data['user_id'] . ' 
				AND ' . $db->sql_in_set('category_id', $moved_ids, true);
		$result = $db->sql_query($sql);
		$row = $db->sql_fetchrow($result);
		$db->sql_freeresult($result);

		$diff = '+ ' . ($row['right_id'] - $from_data['left_id'] + 1);
	}

	$sql = 'UPDATE ' . XSPACE_CATEGORIES_TABLE . "
		SET left_id = left_id $diff, right_id = right_id $diff 
		WHERE category_type = " . CATEGORY_CATEGORY . ' AND  creator_id = ' . $user->data['user_id'] . ' 
			AND ' . $db->sql_in_set('category_id', $moved_ids);
	$db->sql_query($sql);
}

/**
* Move category position by $steps up/down
*/
function move_category_by($category_row, $action = 'move_up', $steps = 1)
{
	global $db, $user;

	/**
	* Fetch all the siblings between the module's current spot
	* and where we want to move it to. If there are less than $steps
	* siblings between the current spot and the target then the
	* module will move as far as possible
	*/
	$sql = 'SELECT category_id, category_name, left_id, right_id
		FROM ' . XSPACE_CATEGORIES_TABLE . '
		WHERE parent_id = ' . $category_row['parent_id'] . ' 
			AND category_type = ' . CATEGORY_CATEGORY . ' AND  creator_id = ' . $user->data['user_id'] . ' 
			AND ' . (($action == 'move_up') ? "right_id < {$category_row['right_id']} ORDER BY right_id DESC" : "left_id > {$category_row['left_id']} ORDER BY left_id ASC");
	$result = $db->sql_query_limit($sql, $steps);

	$target = array();
	while ($row = $db->sql_fetchrow($result))
	{
		$target = $row;
	}
	$db->sql_freeresult($result);

	if (!sizeof($target))
	{
		// The category is already on top or bottom
		return false;
	}

	/**
	* $left_id and $right_id define the scope of the nodes that are affected by the move.
	* $diff_up and $diff_down are the values to substract or add to each node's left_id
	* and right_id in order to move them up or down.
	* $move_up_left and $move_up_right define the scope of the nodes that are moving
	* up. Other nodes in the scope of ($left_id, $right_id) are considered to move down.
	*/
	if ($action == 'move_up')
	{
		$left_id = $target['left_id'];
		$right_id = $category_row['right_id'];

		$diff_up = $category_row['left_id'] - $target['left_id'];
		$diff_down = $category_row['right_id'] + 1 - $category_row['left_id'];

		$move_up_left = $category_row['left_id'];
		$move_up_right = $category_row['right_id'];
	}
	else
	{
		$left_id = $category_row['left_id'];
		$right_id = $target['right_id'];

		$diff_up = $category_row['right_id'] + 1 - $category_row['left_id'];
		$diff_down = $target['right_id'] - $category_row['right_id'];

		$move_up_left = $category_row['right_id'] + 1;
		$move_up_right = $target['right_id'];
	}

	// Now do the dirty job
	$sql = 'UPDATE ' . XSPACE_CATEGORIES_TABLE . "
		SET left_id = left_id + CASE
			WHEN left_id BETWEEN {$move_up_left} AND {$move_up_right} THEN -{$diff_up}
			ELSE {$diff_down}
		END,
		right_id = right_id + CASE
			WHEN right_id BETWEEN {$move_up_left} AND {$move_up_right} THEN -{$diff_up}
			ELSE {$diff_down}
		END 
		WHERE
			category_type = " . CATEGORY_CATEGORY . ' AND  creator_id = ' . $user->data['user_id'] . " 
			AND left_id BETWEEN {$left_id} AND {$right_id}
			AND right_id BETWEEN {$left_id} AND {$right_id}";
	$db->sql_query($sql);

	return $target['category_name'];
}


?>